///////////////////////////////////////////////////////////////////////////////
// Company: University of Cincinnati
// Author: Jordan Ross
//
// Created Date: 09/24/2013
// Design Name:
// Module Name: Proc_tb
// Project Name: Proc
// Target Devices: Cyclone II EP2C20F484C7
// Tool Versions: Quartus 13.0
// Description: This module is a test bench for the Proc module.
// 
// Dependencies: proc.v
// 
// Revision:
// 0.01 - File Created and Initial Tests
// 0.02 - Added test cases.
// Additional Comments:
//
///////////////////////////////////////////////////////////////////////////////
module Proc_tb;
	reg [8:0] DIN;
	reg Resetn, Clock, Run;
	wire Done;
	wire [8:0] BusWires;
	//wire [1:0] ErrorLED;
	
	integer fh; // file handler for output
	
	Proc proc_uut(.DIN(DIN), .Resetn(Resetn), .Clock(Clock), .Run(Run), .Done(Done),
		.BusWires(BusWires)/*, .ErrorLED(ErrorLED)*/);
	
	initial begin
	
		// Set up the file to write all outputs to.
		fh = $fopen("Bare_Processor_TestBench_Output.txt", "w");
		
		Clock = 0;
		Resetn = 0;
		Run = 0;
		
		#100;
		
		Resetn = 1;
		#100;
		
		// Start giving inputs here
		
		// First thing we want to do is to load immediates into registers 0-3 to test
		// the MVI instruction.
		$fwrite(fh, "Testing moving immediates into registers...\n");
		// Move the value 0 into register 0
		$fwrite(fh, "MVI 0 0\n");
		DIN = 9'b001000000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		DIN = 9'b000000000;
		#200;
		$fwrite(fh, "Reg[0]=%d\n", proc_uut.R0);
		// Move the value 341 into register 1
		$fwrite(fh, "MVI 1 341\n");
		DIN = 9'b001001000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		DIN = 9'b101010101;
		#200;
		$fwrite(fh, "Reg[1]=%d\n", proc_uut.R1);
		// Move the value 511 into register 2
		$fwrite(fh, "MVI 2 511\n");
		DIN = 9'b001010000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		DIN = 9'b111111111;
		#200;
		$fwrite(fh, "Reg[2]=%d\n", proc_uut.R2);
		// Move the value 3 into register 3
		$fwrite(fh, "MVI 3 3\n");
		DIN = 9'b001011000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		DIN = 9'b000000011;
		#200;
		$fwrite(fh, "Reg[3]=%d\n", proc_uut.R3);
		
		//Second thing we need to do is to load registers 4-7 with values of
		//registers 0-3.
		$fwrite(fh, "Testing moving contents from register to register...\n");
		// Move the contents of register 0 to register 4
		$fwrite(fh, "MV 4 0\n");
		DIN = 9'b000100000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#200;
		$fwrite(fh, "Reg[4]=%d\n", proc_uut.R4);
		// Move the contents of register 1 to register 5
		$fwrite(fh, "MV 5 1\n");
		DIN = 9'b000101001;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#200;
		$fwrite(fh, "Reg[5]=%d\n", proc_uut.R5);
		// Move the contents of register 2 to register 6
		$fwrite(fh, "MV 6 2\n");
		DIN = 9'b000110010;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#200;
		$fwrite(fh, "Reg[6]=%d\n", proc_uut.R6);
		// Move the contents of register 3 to register 7
		$fwrite(fh, "MV 7 3\n");
		DIN = 9'b000111011;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#200;
		$fwrite(fh, "Reg[7]=%d\n", proc_uut.R7);
		
		// What happens if we reference ourself on a move?
		
		// Now we test addition using boundary cases. The cases we want to try are:
		// 0+0 = 0
		// 511+511 = 510
		// 511+0 = 511
		// 341+3 = 344
		$fwrite(fh, "Now testing addition... \n");
		// Test 0+0 = 0
		$fwrite(fh, "ADD reg[0] reg[4] = 0 + 0\n");
		DIN = 'b010000100;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "0+0=%d, reg[0]=%d\n",proc_uut.R0, proc_uut.R0);
		// Test 511+511= 510
		$fwrite(fh, "ADD reg[2] reg[6] = 511 + 511\n");
		DIN = 'b010010110;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "511+511=%d, reg[2]=%d\n",proc_uut.R2, proc_uut.R2);
		// Test 511+0 = 0
		$fwrite(fh, "ADD reg[4] reg[6] = 0 + 511\n");
		DIN = 'b010100110;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "0+511=%d, reg[4]=%d\n",proc_uut.R4, proc_uut.R4);
		// Test 0+0 = 0
		$fwrite(fh, "ADD reg[1] reg[7] = 341 + 3\n");
		DIN = 'b010001111;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "341+3=%d, reg[1]=%d\n",proc_uut.R1, proc_uut.R1);
		
		// Now we test subtract using boundary cases. The cases we want to try are:
		// 0-0 =0
		// 511-511 = 0
		// 511-0 = 511
		// 344-341 = 3
		$fwrite(fh, "Now testing subtraction... \n");
		// Test 0-0 = 0
		$fwrite(fh, "SUB reg[0] reg[0] = 0 - 0\n");
		DIN = 'b011000000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "0-0=%d, reg[0]=%d\n",proc_uut.R0, proc_uut.R0);
		// Test 511-511= 0
		$fwrite(fh, "SUB reg[4] reg[6] = 511 - 511\n");
		DIN = 'b011100110;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "511-511=%d, reg[4]=%d\n",proc_uut.R4, proc_uut.R4);
		// Test 511-0 = 511
		$fwrite(fh, "SUB reg[6] reg[0] = 511 - 0\n");
		DIN = 'b011110000;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "511-0=%d, reg[6]=%d\n",proc_uut.R6, proc_uut.R6);
		// Test 344-341 = 0
		$fwrite(fh, "SUB reg[1] reg[5] = 344 - 341\n");
		DIN = 'b011001101;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "341-3=%d, reg[1]=%d\n",proc_uut.R1, proc_uut.R1);
		// Test 0-511 = 0
		$fwrite(fh, "SUB reg[0] reg[6] = 0 - 511\n");
		DIN = 'b011000110;
		#100;
		Run = 1;
		#100;
		Run = 0;
		#300;
		$fwrite(fh, "0-511=%d, reg[0]=%d\n",proc_uut.R0, proc_uut.R0);
		
		$fwrite(fh, "Testing Done!");
		// Close the output file
		$fclose(fh);
		
	end
	
	always begin
		#50 Clock = !Clock;
	end
	
endmodule
